﻿package net.wangit.user;

import java.util.Map;

import net.wangit.LabelUtil;
import net.wangit.MapList;
import net.wangit.Row;
import net.wangit.User;
import net.wangit.Visitor;
import net.wangit.context.ActionContext;
import net.wangit.context.ActionResult;
import net.wangit.framework.config.ProjectSettings;
import net.wangit.framework.util.MapListUtil;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.DBFactory;
import net.wangit.jdbc.Type;
import net.wangit.user.privilege.PrivilegeUtil;
import net.wangit.util.Checker;
import net.wangit.util.DateUtil;
import net.wangit.util.Md5Encoder;


/**
 * 用户工厂
 * 
 * @author watson Feb 23, 2010
 */
public class UserFactory {

	private static final String SQL_USER_LOGIN = "select * from AUSER where userid=? and password=?";
	private static final String SQL_USER = "select * from AUSER where userid=? ";
	private static final String SQL_GROUPS = "select groupid from AUSERGROUP where userid=?";
	private static final String SQL_ALL_ROLES = "select roleid from AROLE where roleid not in (select roleid from AUSERROLE where userid=? and hold=0) and ( roleid in (select roleid from AROLE where parentid is null or parentid='') or roleid in (select roleid from AUSERROLE where userid=? and hold=1) or roleid in (select t1.roleid from AORGROLE t1,AUSER t2 where t1.orgid = t2.orgid and t2.userid=?) or roleid in (select t3.roleid from AGROUPROLE t3, AUSERGROUP t4 where t3.groupid=t4.groupid and t4.userid=?))";
	private static final String SQL_PRIVILEGES = "select * from AROLEPRIVILEGE where roleid not in (select roleid from AROLE where enabled=0) and roleid not in (select roleid from AUSERROLE where userid=? and hold=0) and ( roleid in (select roleid from AROLE where parentid is null or parentid='') or roleid in (select roleid from AUSERROLE where userid=? and hold=1) or roleid in (select t1.roleid from AORGROLE t1,AUSER t2 where t1.orgid = t2.orgid and t2.userid=?) or roleid in (select t3.roleid from AGROUPROLE t3, AUSERGROUP t4 where t3.groupid=t4.groupid and t4.userid=? and t3.groupid not in (select groupid from AGROUP where enabled=0)))";

	private UserFactory() {
	}

	/*
	 * 获取用户
	 */
	public static User getUser(ActionContext ac, String userId, String password)
			throws Exception {
		DB db = DBFactory.getDB();
		MapList list = db.query(UserFactory.SQL_USER_LOGIN, new String[] {
				userId, Md5Encoder.encode(password) }, new int[] {
				Type.VARCHAR, Type.VARCHAR });
		if (Checker.isEmpty(list)) {
			ActionResult ar = ac.getActionResult();
			ar.setSuccessful(false);
			ar.addError(LabelUtil.get(ac, "system", "login.failed"));
			return null;
		}
		Row row = list.getRow(0);
		int userLevel = row.getInt("userlevel", 1);
		String expiredDate = row.get("expireddate");
		if (userLevel < UserLevel.SUPER_USER
				&& !Checker.isEmpty(expiredDate)
				&& DateUtil.getGapByMillisecond(expiredDate, DateUtil
						.getCurrentDate()) >= 0L) {
			ActionResult ar = ac.getActionResult();
			ar.setSuccessful(false);
			ar.addError(LabelUtil.get(ac, "system", "login.expired"));
			return null;
		} else {
			User user = createUser(db, row);
			Visitor visitor = ac.getVisitor();
			visitor.setUser(user);
			return user;
		}
	}

	public static User getUser(String userId) throws Exception {
		DB db = DBFactory.getDB();
		MapList list = db.query(UserFactory.SQL_USER, userId, Type.VARCHAR);
		boolean pass = !Checker.isEmpty(list);
		if (pass) {
			User user = createUser(db, list.getRow(0));
			return user;
		} else {
			return null;
		}
	}

	private static User createUser(DB db, Row row) throws Exception {
		String userId = row.get("userid");
		int userLevel = row.getInt("userlevel", 1);
		RegisteredUser user;
		switch (userLevel) {
		case UserLevel.PROJECT_MANAGER:
			user = new ProjectManager(userId);
			break;

		case UserLevel.DEVELOPER:
			user = new Developer(userId);
			break;

		case UserLevel.SUPER_USER:
			if (ProjectSettings.instance().getSuperUserOption() == SuperUserOption.LIMITED)
				user = new LimitedSuperUser(userId);
			else
				user = new SuperUser(userId);
			break;

		case UserLevel.ADMINISTRATOR_USER:
			user = new AdminUser(userId);
			break;

		default:
			user = new RegisteredUser(userId);
			break;
		}
		user.setName(row.get("username"));
		user.setOrganization(row.get("orgid"));
		user.set(row.toMap());
		user.setGroups(getGroups(db, userId));
		user.setAllRoles(getAllRoles(db, userId));
		user.setPrivileges(getPrivileges(db, userId));
		user.configure(row);
		return user;
	}

	private static String[] getGroups(DB db, String userId) throws Exception {
		MapList groups = db.query(UserFactory.SQL_GROUPS, userId, Type.VARCHAR);
		return MapListUtil.getArray(groups, "groupid");
	}

	private static String[] getAllRoles(DB db, String userId) throws Exception {
		MapList allRoles = db.query(UserFactory.SQL_ALL_ROLES, new String[] {
				userId, userId, userId, userId }, new int[] { Type.VARCHAR,
				Type.VARCHAR, Type.VARCHAR, Type.VARCHAR });
		return MapListUtil.getArray(allRoles, "roleid");
	}

	public static Map getPrivileges(DB db, String userId) throws Exception {
		MapList list = db.query(UserFactory.SQL_PRIVILEGES, new String[] {
				userId, userId, userId, userId }, new int[] { Type.VARCHAR,
				Type.VARCHAR, Type.VARCHAR, Type.VARCHAR });
		return PrivilegeUtil.getPrivileges(list);
	}
}
